package com.itheima.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itheima.dao.AdminMapper;
import com.itheima.dao.CategotyMenuMapper;
import com.itheima.dao.FileMapper;
import com.itheima.dao.RoleMapper;
import com.itheima.pojo.*;
import com.itheima.pojo.Admin;

import com.itheima.service.AdminService;
import com.itheima.utils.CookieUtils;

import com.itheima.utils.IdWorker;
import com.itheima.utils.IpUtils;
import com.itheima.utils.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpCookie;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Service
public class AdminServiceImpl implements AdminService {


    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private CategotyMenuMapper categotyMenuMapper;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    //设置token标签
    private static final String BEARER = "bearer_";
    //设置redis中token的键标签
    private static final String LOGIN = "LOGIN_";

    //获取管理员角色信息
    @Override
    public Map<String, Object> info(String username,HttpServletRequest request) throws Exception {

        // {"roles":[{"roleName":"","summary":"","categoryMenuUids":"","uid":"434994947c5a4ee3a710cd277357c7c3","status":1,"createTime":"2018-10-16 07:56:26","updateTime":"2020-06-15 10:39:59"}],"avatar":"http://localhost:8600//blog/admin/jpg/2020/2/24/1582507546061.jpg","token":""}

        String token=null;
        //获取cookie中的token
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            if ("Authorization".equals(name)){
                token = cookie.getValue();}}

        //1 查询当前用户对应的角色id avatar
        Map<String,Object> map=adminMapper.findRoleIdAndAvatar(username);
        String roleUid = (String) map.get("roleUid");
        String avatar = (String) map.get("avatar");
        String picUrl = fileMapper.getPicUrl2ByUid(avatar);

        //2 根据角色id 查询t_role,根据file id 查询t_file
        Role role= roleMapper.findRoleByUid2(roleUid);

        HashMap<String, Object> map2 = new HashMap<>();

        ArrayList<Map<String, Object>> list = new ArrayList<>();

        map2.put("roleName",role.getRoleName());
        map2.put("summary",role.getSummary());
        map2.put("categoryMenuUids",role.getCategoryMenuUids());
        map2.put("uid",role.getUid());
        map2.put("status",role.getStatus());
        map2.put("createTime",DateUtils.parseDate2String(role.getCreateTime()));
        map2.put("updateTime",DateUtils.parseDate2String(role.getUpdateTime()));
        list.add(map2);

        HashMap<String, Object> result = new HashMap<>();

        //封装数据
        result.put("roles",list);
        result.put("avatar",picUrl);
        result.put("token",token);
       //返回结果
        return result;
    }

    //查询管理员列表数据
    @Override
    public PageInfo<Admin> getList(String keyword,Integer currentPage,Integer pageSize) {

        PageHelper.startPage(currentPage,pageSize );
        Example example = createExample(keyword);
        List<Admin> adminList = adminMapper.selectByExample(example);

        for (Admin admin : adminList ) {
            String avatar = admin.getAvatar();

            //封装管理员图片数据 List<String>photoList;
            String picUrl2ByUid = fileMapper.getPicUrl2ByUid(avatar);
            List<String> photoList= new ArrayList<>();
            photoList.add(picUrl2ByUid);
            admin.setPhotoList(photoList);

            //封装管理员角色数据  role
            String roleUid = admin.getRoleUid();
            System.out.println(roleUid+"roleUid===============");
            Role role = roleMapper.findRoleByUid(roleUid);
            admin.setRole(role);
        }

        PageInfo<Admin> pageInfo = new PageInfo<>(adminList);
        return pageInfo;
    }



    //1.注册管理员
    @Override
    public int add(AdminVO adminVO, HttpServletRequest request) throws Exception {

        Admin admin = new Admin();
        admin.setAvatar(adminVO.getAvatar());
        admin.setBirthday(DateUtils.parseString2Date(adminVO.getBirthday()));
        admin.setCreateTime(new Date());
        admin.setEmail(adminVO.getEmail());
        admin.setGender(adminVO.getGender());
        admin.setGitee(adminVO.getGitee());
        admin.setGithub(adminVO.getGithub());
        String ipAddr = IpUtils.getIpAddr(request);
        admin.setLastLoginIp(ipAddr);
        admin.setLastLoginTime(new Date());
        admin.setLoginCount(0);
        admin.setMobile(adminVO.getMobile());
        admin.setNickName(adminVO.getNickName());
        admin.setOccupation(adminVO.getOccupation());
        //设置用户初始密码
        admin.setPassWord(bCryptPasswordEncoder.encode("123456"));
        admin.setPersonResume(adminVO.getPersonResume());
        admin.setQqNumber(adminVO.getQqNumber());
        admin.setRoleUid(adminVO.getRoleUid());
        admin.setStatus(adminVO.getStatus());
        admin.setSummary(adminVO.getSummary());
        admin.setUid(idWorker.nextId()+"");
        admin.setUpdateTime(new Date());
        admin.setUserName(adminVO.getUserName());
        admin.setValidCode(adminVO.getValidCode());
        admin.setWeChat(adminVO.getWeChat());

       // List<String> photoList = adminVO.getPhotoList();

        String roleUid = adminVO.getRoleUid();
        Role role1 = roleMapper.findRoleByUid(roleUid);
        String roleName = role1.getRoleName();

        Role role = new Role();
        role.setUid(idWorker.nextId()+"");

        role.setRoleName(roleName);
        role.setCreateTime(new Date());
        role.setUpdateTime(new Date());
        role.setStatus(1);
        roleMapper.insert(role);

      /*  File file = new File();
        for (String url : photoList) {
            file.setPicUrl(url);
            file.setCreateTime(new Date());
            file.setUpdateTime(new Date());
            file.setUid(idWorker.nextId()+"");
        }

        fileMapper.insert(file);*/
        //admin.setAvatar(file.getUid());
        admin.setRoleUid(role.getUid());
        return adminMapper.insertSelective(admin);

    }

    //2.分配用户角色信息列表 POST /admin/assign  (adminUid  管理员uid)
    @Override
    public Map assign(String adminUid) throws Exception {
        //"admin":{"userName":"test1","roleUid":"434994947c5a4ee3a710cd277357c7c3","passWord":"$2a$10$aoFCunMkKlqkWIZJ/p1Sn.n5eLBLuXKroqyX7Blo/kOJdRquJsIeG","nickName":"test1","gender":"1","avatar":",70f5b89fe70a28d95e10c19c96bf2e85","email":"1595833114@qq.com","loginCount":46,"lastLoginTime":"2020-06-09 18:52:03","lastLoginIp":"192.168.80.1","uid":"1723ad77a1ca06b29a011471036a2dd6","status":0,"createTime":"2020-03-22 10:23:12","updateTime":"2020-08-07 11:16:46"}
        Admin admin = adminMapper.findAdminByUid(adminUid);
        HashMap<String, Object> map1 = new HashMap<>();
        map1.put("userName",admin.getUserName());
        map1.put("roleUid",admin.getRoleUid());
        map1.put("nickName",admin.getNickName());
        map1.put("gender",admin.getGender());
        map1.put("avatar",admin.getAvatar());
        map1.put("email",admin.getEmail());
        map1.put("loginCount",admin.getLoginCount());
        map1.put("lastLoginTime",admin.getLastLoginTime());
        map1.put("lastLoginIp",admin.getLastLoginIp());
        map1.put("uid",admin.getLastLoginIp());
        map1.put("status",admin.getLastLoginIp());
        map1.put("createTime",admin.getCreateTime());
        map1.put("updateTime",admin.getUpdateTime()); //封装admin数据

        String roleUid = admin.getRoleUid();

        ArrayList<Map<String,Object>> assignedRoles= new ArrayList<>();
        Role role= roleMapper.findRoleByUid2(roleUid);

        //封装用户被分配的角色数据
        HashMap<String, Object> map4 = new HashMap<>();
        map4.put("roleName",role.getRoleName());
        map4.put("summary",role.getSummary());
        map4.put("categoryMenuUids",role.getCategoryMenuUids());
        map4.put("uid",role.getUid());
        map4.put("status",role.getStatus());
        map4.put("createTime",DateUtils.parseDate2String(role.getCreateTime()));
        map4.put("updateTime",DateUtils.parseDate2String(role.getUpdateTime()));

        assignedRoles.add(map4);


        //封装用户没有被分配的角色数据
        //role_name roleName,summary,category_menu_uids categoryMenuUids,uid,status,create_time createTime,update_time updateTime
        List<Role> list = roleMapper.findRoleListByUid3(roleUid);
        List<Map<String,Object>>unassignRoles=new ArrayList<>();
        for (Role unassignRole : list) {

            HashMap<String, Object> map2 = new HashMap<>();
            map2.put("roleName",unassignRole.getRoleName());
            map2.put("summary",unassignRole.getSummary());
            map2.put("categoryMenuUids",unassignRole.getCategoryMenuUids());
            map2.put("uid",unassignRole.getUid());
            map2.put("status",unassignRole.getStatus());
            map2.put("createTime",DateUtils.parseDate2String(unassignRole.getCreateTime()));
            map2.put("updateTime",DateUtils.parseDate2String(unassignRole.getUpdateTime()));
            unassignRoles.add(map2);
        }

        //封装数据
        Map<String, Object> map2 = new HashMap<>();
        map2.put("unassignRoles",unassignRoles);
        map2.put("assignedRoles",assignedRoles);
        map2.put("admin",map1);
        //返回结果
        return map2;
    }

    //3.用户登录成功后，将令牌存入redis中
    @Override
    public String getJwtFromRedis(String username) {
           return (String) redisTemplate.boundValueOps(username).get();
    }

    //4.用户登录成功后，从cookie中获取令牌
    @Override
    public String getJwtFromCookie(ServerHttpRequest request) {
        HttpCookie httpCookie = request.getCookies().getFirst("Authorization");
        if (httpCookie != null){
          return httpCookie.getValue();
        }
        return null;
    }

     //1. 管理员用户登录
    @Override
    public Result login(Map map,HttpServletRequest request) {

        Admin admin = new Admin();
        admin.setUserName((String) map.get("username"));
        Admin admin1 = adminMapper.selectOne(admin);
        //当前用户登录成功修改最近登录时间，修改增加登录次数，查询IP地址，响应cookie
        if (admin1!=null){

            if (bCryptPasswordEncoder.matches((String) map.get("password"),admin1.getPassWord())){
                //用户存在,并且密码正确，为登录成功
                Map<String, Object>  claims = new HashMap<>();
                //设置载荷,token 中保存用户名和用户uid
                claims.put("username",admin1.getUserName());
                claims.put("uid",admin1.getUid());
                String token = TokenUtil.createJavaWebToken(claims);
                //用户登录成功，响应cookie，浏览器关闭，重新登录
                HttpSession session = request.getSession();
                //session.setAttribute("");
                CookieUtils.setCookie("Authorization",BEARER+token,-1);
                redisTemplate.boundValueOps(LOGIN+admin1.getUserName()).set(BEARER+token,60, TimeUnit.MINUTES);
                admin1.setLoginCount(admin1.getLoginCount()+1);
                admin1.setLastLoginTime(new Date());
                admin1.setLastLoginIp(IpUtils.getRealIp(request));
                adminMapper.updateByPrimaryKey(admin1);
                return new Result(StatusCode.OK,"登录成功");
            }
            //返回用户登录结果
            return new Result(StatusCode.ERROR,"密码错误");
        }
        return new Result(StatusCode.ERROR,"用户名不存在");
    }

    //6.3 更新管理员密码
    @Override
    public int updatePassWord(Map map) {
        //newPassWord
       String  newPassWord = (String)map.get("newPassWord");
       String  userInfo= (String)map.get("userInfo");
        Admin admin = new Admin();
        Example example = new Example(User.class);
        Example.Criteria criteria = example.createCriteria();

        if (userInfo != null && !"".equals(userInfo )) {
            criteria.andEqualTo("user_name", userInfo);
        }

        admin.setUserName(userInfo);
        //重新加密
        String encode = bCryptPasswordEncoder.encode(newPassWord);
        admin.setPassWord(encode);
        return adminMapper.updateByExample(admin, example);
    }
    //6.1 校验用户名是否存在
    @Override
    public Admin findAdmin1ByName(String userInfo) {
        Admin admin = new Admin();
        admin.setUserName(userInfo);
       return  adminMapper.selectOne(admin);
    }
    //6.2 校验用户的旧密码是否正确
    @Override
    public Boolean findAdmin2BypassWord(String passWord,Admin admin) {
        String passWord1 = admin.getPassWord();
        return bCryptPasswordEncoder.matches(passWord,passWord1);
    }


    //7 获取当前用户的菜单
    @Override
    public Map getMenu(Map<String, Object> userInfo) throws Exception {
        String username = (String)userInfo.get("username");

        HashMap<String, Object> result = new HashMap<>();
        Map<String, Object> roleIdAndAvatar = adminMapper.findRoleIdAndAvatar(username);
        String roleUid = (String) roleIdAndAvatar.get("roleUid");
        Role role= roleMapper.findRoleByUid2(roleUid);
        String categoryMenuUids = role.getCategoryMenuUids();
        List list = JSON.parseObject(categoryMenuUids, List.class);

        List<CategoryMenu> sonList = new ArrayList<>();
        List<CategoryMenu> parentList = new ArrayList<>();
        List<CategoryMenu> buttonList=new ArrayList<>();

        for (Object uid : list) {

            //查询所有的子菜单数据，并且封装到sonList集合中
            CategoryMenu categoryMenu = categotyMenuMapper.findCategoryMenuList(uid);
            Integer menuLevel = categoryMenu.getMenuLevel();
            if (menuLevel==1){
                parentList.add(categoryMenu);
            } else if (menuLevel==2){
                sonList.add(categoryMenu);
            }else {
                buttonList.add(categoryMenu);
            }
        }

        //封装结果
        result.put("sonList",sonList);
        result.put("buttonList",buttonList);
        result.put("parentList",parentList);

        //返回结果
        return result;
    }

    //8.更新管理员邮箱或手机号
    @Override
    public int updateEmail(Map map) {
        Admin admin = new Admin();
        String uid = (String) map.get("uid");
        String newInfo = (String) map.get("newInfo");

        if (newInfo.length()==11&&!newInfo.contains("@")){
            admin.setUid(uid);
            admin.setMobile(newInfo);
            return adminMapper.updateByPrimaryKey(admin);
        }
        admin.setUid(uid);
        admin.setEmail(newInfo);
        return adminMapper.updateByPrimaryKey(admin);
    }

    //9.根据管理员uid重置用户密码
    @Override
    public int restPwd(String uid) {
        Admin admin = new Admin();
        admin.setUid(uid);
        Admin admin1 = adminMapper.selectOne(admin);
        String userName = admin1.getUserName();
        admin.setUserName(userName);
        //重置用户密码为初始密码123456
        String encode = bCryptPasswordEncoder.encode("123456");
        admin.setPassWord(encode);
        admin.setStatus(1);
        return adminMapper.updateByPrimaryKey(admin);

    }

    //10. 删除部分管理员信息
    @Override
    public int delete(String adminUidS) {
         return adminMapper.deleteByPrimaryKey(adminUidS);
    }

    //11.更新管理员基本信息
    @Override
    public int edit(AdminVO adminVO,HttpServletRequest request) throws Exception {

        Admin admin = new Admin();
        admin.setAvatar(adminVO.getAvatar());
        admin.setUserName(adminVO.getUserName());
        admin.setRoleUid(adminVO.getRoleUid());
        admin.setNickName(adminVO.getNickName());
        admin.setGender(adminVO.getGender());
        admin.setEmail(adminVO.getEmail());
        admin.setQqNumber(adminVO.getQqNumber());
        admin.setMobile(adminVO.getMobile());
        admin.setOccupation(adminVO.getOccupation());
        admin.setPassWord(adminVO.getPassWord());

        admin.setCreateTime(new Date());
        admin.setUpdateTime(new Date());
        String ipAddr = IpUtils.getIpAddr(request);
        admin.setLastLoginIp(ipAddr);
        admin.setLastLoginTime(new Date());
        admin.setLoginCount(adminVO.getLoginCount());

        admin.setStatus(adminVO.getStatus());
        admin.setUid(adminVO.getUid());

        //List<String> photoList = adminVO.getPhotoList();
 /*       Role role = adminVO.getRole();
        roleMapper.insert(role);
*/
       /* File file = new File();
        for (String url : photoList) {
            file.setPicUrl(url);
            file.setCreateTime(new Date());
            file.setUpdateTime(new Date());
            file.setUid(idWorker.nextId()+"");
        }
        fileMapper.insert(file);
        admin.setAvatar(file.getUid());*/
        return adminMapper.updateByPrimaryKey(admin);
    }

    //12. 获取在线管理员
    @Override
    public List<Map<String,Object>> getOnlineAdminList(String uid,HttpServletRequest request) {
      //{"code":"success","data":[{"tokenId":"bearer_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhZG1pblVpZCI6IjFmMDFjZDFkMmY0NzQ3NDNiMjQxZDc0MDA4YjEyMzMzIiwicm9sZSI6Im51bGzotoXnuqfnrqHnkIYiLCJjcmVhdFRpbWUiOjE1OTY4ODg0NTk5MDEsInN1YiI6ImFkbWluIiwiaXNzIjoibW9ndWJsb2ciLCJhdWQiOiIwOThmNmJjZDQ2MjFkMzczY2FkZTRlODMyNjI3YjRmNiIsImV4cCI6MTU5NzE0NzY1OSwibmJmIjoxNTk2ODg4NDU5fQ.UL9_iMI-pYg8aX_7z1N2fAFvofYYdamfxJC9-iNoJU8","adminUid":"1f01cd1d2f474743b241d74008b12333","userName":"admin","ipaddr":"192.168.71.112","loginLocation":"内网IP|内网IP","browser":"Chrome-83.0.4103.97","os":"Windows","roleName":"超级管理员","loginTime":"2020-08-08 20:07:39"}]}

        String token=null;
        //获取cookie中的token
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            if ("Authorization".equals(name)){
                token = cookie.getValue();}}


        Map<String, Object> userNameAndLoginTime = adminMapper.findUserNameAndLoginTime(uid);
        String userName = (String) userNameAndLoginTime.get("userName");
        String roleUid = (String) userNameAndLoginTime.get("roleUid");
        Role role = roleMapper.findRoleByUid(roleUid);
        String roleName = role.getRoleName();
        Date lastLoginTime = (Date) userNameAndLoginTime.get("lastLoginTime");
        String loginTime=null;
        try {
            loginTime = DateUtils.parseDate2String(lastLoginTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //获取当前网络ip
        String ipAddr = IpUtils.getIpAddr(request);

        ArrayList<Map<String,Object>> list = new ArrayList<>();

        Map<String, Object> map = new HashMap<>();
        map.put("tokenId",token);
        map.put("adminUid",uid);
        map.put("userName",userName);
        map.put("ipaddr",ipAddr);

        //判断是否是内网IP
        boolean inner = IpUtils.isInner(ipAddr);
        if (inner){
            map.put("loginLocation","内网IP|内网IP");
            Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
            String os = osAndBrowserInfo.get("OS");
            String browser = osAndBrowserInfo.get("BROWSER");
            map.put("os",os);
            map.put("browser",browser);
            map.put("roleName",roleName);
            map.put("loginTime",loginTime);
            list.add(map);
        }else {
            map.put("loginLocation",null);
            Map<String, String> osAndBrowserInfo = IpUtils.getOsAndBrowserInfo(request);
            String os = osAndBrowserInfo.get("OS");
            String browser = osAndBrowserInfo.get("BROWSER");
            map.put("os",os);
            map.put("browser",browser);
            map.put("roleName",roleName);
            map.put("loginTime",loginTime);
            list.add(map);
        }
        return list;
    }


    /*
     * 封装查询条件对象*/
    private Example createExample(String keyword) {
        Example example = new Example(Admin.class);
        Example.Criteria criteria = example.createCriteria();
        if (keyword!= null) {
            // 根据用户名称模糊查询
            if (!"".equals(keyword)) {
                criteria.andLike("userName", "%" + keyword + "%");
            }
        }
        return example;
    }
}
